home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 59454 / 59454.xpi / content / overlay.js < prev    next >
Text File  |  2010-01-26  |  22KB  |  526 lines

  1.  
  2. BartUniversalSearch.UniversalSearchClass = BartUtils.defineClass(
  3. {
  4.     name: "UniversalSearchClass",
  5.     construct: function()
  6.                 {
  7.                     this.bubble = new BartUniversalSearch.BubbleClass();
  8.                     
  9.                     // name of the default engine
  10.                     var defaultEngineName = BartUniversalSearch.Preference.getDefaultEngine();
  11.                     var engine = BartUniversalSearch.SearchEngineWrapper.getEngine(defaultEngineName, true);
  12.                     defaultEngineName = engine.getName();
  13.  
  14.                     this._setDefaultEngine(defaultEngineName);
  15.                 },
  16.  
  17.     methods:
  18.     {
  19.         _setDefaultEngine: function(engineName)
  20.         {
  21.             this.defaultEngineName = engineName;
  22.  
  23.             BartUniversalSearch.Preference.setDefaultEngine(engineName);
  24.         },
  25.  
  26.         _getPopupMenu: function()
  27.         {
  28.             return document.getElementById("bart-ibrowser-UniversalSearch-popup");
  29.         },
  30.  
  31.         _openEngineManager: function()
  32.         {
  33.             var mediator = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
  34.  
  35.             var window = mediator.getMostRecentWindow("Browser:SearchManager");
  36.             if (window)
  37.             {
  38.                 window.focus();
  39.             }
  40.             else
  41.             {
  42.                 setTimeout(function ()
  43.                     {
  44.                         openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen");
  45.                     }, 0);
  46.             }
  47.         },
  48.  
  49.         _buildSearchEnginePopupMenu: function(popup)
  50.         {
  51.             var engines = BartUniversalSearch.SearchEngineWrapper.getAvailableSearchEngines();
  52.  
  53.             var menuItem;
  54.             for (var i = 0; i < engines.length; i++)
  55.             {
  56.                 menuItem = document.createElement("menuitem");
  57.  
  58.                 menuItem.setAttribute("label", engines[i].getName());
  59.                 menuItem.setAttribute("tooltiptext", "Search using " + engines[i].getName());
  60.                 menuItem.setAttribute("class", "menuitem-iconic");
  61.  
  62.                 var iconUrl = engines[i].getIconUrl(BartUniversalSearch.UniversalSearchClass.ICON_SEARCHDEFAULT);
  63.                 menuItem.setAttribute("image", iconUrl);
  64.  
  65.                 menuItem.setAttribute(BartUniversalSearch.UniversalSearchClass.ATTR_CMD_ID, BartUniversalSearch.UniversalSearchClass.CMD_ID_SEARCH);
  66.                 menuItem.engine = engines[i].getName();
  67.  
  68.                 if(this.defaultEngineName == engines[i].getName())
  69.                 {
  70.                     menuItem.setAttribute("style", "font-weight:bold");
  71.                 }
  72.  
  73.                 popup.appendChild(menuItem);
  74.             }
  75.  
  76.             if(i > 0)
  77.             {
  78.                 menuItem = document.createElement("menuseparator");
  79.                 popup.appendChild(menuItem);
  80.             }
  81.  
  82.             // create engine management menuitem
  83.             menuItem = document.createElement("menuitem");
  84.             menuItem.setAttribute("label", "Manage Search Engines...");
  85.             menuItem.setAttribute("class", "menuitem-iconic");
  86.             menuItem.setAttribute(BartUniversalSearch.UniversalSearchClass.ATTR_CMD_ID, BartUniversalSearch.UniversalSearchClass.CMD_ID_MANAGEENGINE);
  87.  
  88.             popup.appendChild(menuItem);
  89.         },
  90.  
  91.         _showSearchEngineMenu: function(anchor)
  92.         {
  93.             var popup = this._getPopupMenu();
  94.             
  95.             if(popup)
  96.             {
  97.                 // Remove old
  98.                 BartDOMUtils.removeAllChildren(popup);
  99.  
  100.                 this._buildSearchEnginePopupMenu(popup);
  101.                 this._attachEventListener(popup.getElementsByTagName("menuitem"), "click");
  102.  
  103.                 popup.openPopup(anchor, "after_start", 0, 0, true, true);
  104.             }
  105.         },
  106.  
  107.         _init: function()
  108.         {
  109.         },
  110.  
  111.         _getFocusedDocument: function()
  112.         {
  113.             return document.commandDispatcher.focusedWindow.document;
  114.         },
  115.  
  116.         _createBubble: function()
  117.         {
  118.             var icons = [];
  119.  
  120.             var imgProps = {};
  121.             var linkProps = {};
  122.             imgProps["alt"] = "";
  123.             imgProps["class"] = "universalsearch-bubble-icon";
  124.             //imgProps["draggable"] = "false";
  125.             imgProps["ondragstart"] = "return false;";
  126.             //linkProps["draggable"] = "false";
  127.             linkProps["ondragstart"] = "return false;";
  128.             linkProps["class"] = "universalsearch-bubble-link";
  129.             linkProps["onclick"] = "return false;";
  130.  
  131.             if(BartUniversalSearch.Preference.showCopyButton())
  132.             {
  133.                 imgProps[BartUniversalSearch.UniversalSearchClass.ATTR_CMD_ID] = BartUniversalSearch.UniversalSearchClass.CMD_ID_COPY;
  134.                 imgProps["id"] = BartUniversalSearch.UniversalSearchClass.CMD_ID_COPY;
  135.                 imgProps["src"] = BartUniversalSearch.UniversalSearchClass.ICON_COPY;
  136.                 imgProps["title"] = "Copy";
  137.                 icons.push(this.bubble.createIcon(imgProps, linkProps));
  138.             }
  139.  
  140.             imgProps[BartUniversalSearch.UniversalSearchClass.ATTR_CMD_ID] = BartUniversalSearch.UniversalSearchClass.CMD_ID_SEARCH;
  141.             imgProps["id"] = BartUniversalSearch.UniversalSearchClass.CMD_ID_SEARCH;
  142.  
  143.             var defaultEngine = BartUniversalSearch.SearchEngineWrapper.getEngine(this.defaultEngineName, true);
  144.             var engineIconUrl = defaultEngine.getIconUrl(BartUniversalSearch.UniversalSearchClass.ICON_SEARCHDEFAULT);
  145.  
  146.             imgProps["src"] = engineIconUrl;
  147.             imgProps["class"] = "universalsearch-bubble-icon";
  148.             imgProps["title"] = this._getSearchButtonTitle(defaultEngine.getName());
  149.             icons.push(this.bubble.createIcon(imgProps, linkProps));
  150.  
  151.             imgProps[BartUniversalSearch.UniversalSearchClass.ATTR_CMD_ID] = BartUniversalSearch.UniversalSearchClass.CMD_ID_MORESEARCHES;
  152.             imgProps["id"] = BartUniversalSearch.UniversalSearchClass.CMD_ID_MORESEARCHES;
  153.             imgProps["src"] = BartUniversalSearch.UniversalSearchClass.ICON_DOWNARROW;
  154.             imgProps["class"] = "universalsearch-bubble-dropdownicon";
  155.             imgProps["title"] = "More searches...";
  156.             linkProps["class"] = "universalsearch-bubble-dropdownlink";
  157.             icons.push(this.bubble.createIcon(imgProps, linkProps));
  158.  
  159.             return this.bubble.createBubble(this._getFocusedDocument(), icons);
  160.         },
  161.  
  162.         _handleBubbleEvent: function(event)
  163.         {
  164.             var element = event.target;
  165.             //if(element.tagName.toLowerCase() == ("img"))
  166.             {
  167.                 var cmdId = element.getAttribute(BartUniversalSearch.UniversalSearchClass.ATTR_CMD_ID);
  168.  
  169.                 switch(cmdId)
  170.                 {
  171.                     case BartUniversalSearch.UniversalSearchClass.CMD_ID_COPY:
  172.                         {
  173.                             goDoCommand("cmd_copy");
  174.                         }
  175.                         break;
  176.  
  177.                     case BartUniversalSearch.UniversalSearchClass.CMD_ID_MORESEARCHES:
  178.                         {
  179.                             this._showSearchEngineMenu(element);
  180.                         }
  181.                         break;
  182.  
  183.                     case BartUniversalSearch.UniversalSearchClass.CMD_ID_MANAGEENGINE:
  184.                         {
  185.                             this._openEngineManager();
  186.                         }
  187.                         break;
  188.  
  189.                     case BartUniversalSearch.UniversalSearchClass.CMD_ID_SEARCH:
  190.                         {
  191.                             var engine = element.engine;
  192.                             
  193.                             if(engine)
  194.                             {
  195.                                 var selectedEngine = BartUniversalSearch.SearchEngineWrapper.getEngine(engine, true);
  196.                                 if(engine != this.defaultEngineName)
  197.                                 {
  198.                                     this._setSearchButtonAttributes(engine,
  199.                                         selectedEngine.getIconUrl(BartUniversalSearch.UniversalSearchClass.ICON_SEARCHDEFAULT));
  200.  
  201.                                     // change default engine
  202.                                     this._setDefaultEngine(engine);
  203.                                 }
  204.                                 
  205.                                 var selection = document.commandDispatcher.focusedWindow.getSelection();
  206.                                 var searchUrl = selectedEngine.getSearchUrl(selection.toString().trim());
  207.  
  208.                                 BartUniversalSearch.UniversalSearchClass.openSearchPage(searchUrl);
  209.                             }
  210.                         }
  211.                         break;
  212.  
  213.                     event.cancelBubble = true;
  214.                     //event.preventDefault();
  215.  
  216.                     return false;
  217.                 }
  218.             }
  219.         },
  220.  
  221.         _attachEventListener: function(elements, eventName)
  222.         {
  223.             for(var i = 0; i < elements.length; i++)
  224.             {
  225.                 elements[i].addEventListener(eventName, BartUniversalSearch.UniversalSearchClass._onBubbleEvent, false);
  226.             }
  227.         },
  228.  
  229.         onMouseUp: function(event)
  230.         {
  231.             // check if it's left mouse button
  232.             if(event.button != 0)
  233.                 return true;
  234.             
  235.             var popup = this._getPopupMenu();
  236.  
  237.             var doc = this._getFocusedDocument();
  238.             if(!doc)
  239.                 return true;
  240.  
  241.             var target = event.target;
  242.             do
  243.             {
  244.                 if(target == this.bubble.getBubble())
  245.                     return true; // current event is triggered by our bubble
  246.  
  247.                 if(target == popup)
  248.                     return true;
  249.  
  250.                 if(target == doc)
  251.                     break;
  252.  
  253.                 target = target.parentNode;
  254.             }while(target);
  255.  
  256.             if(!target)
  257.                 return true; // not clicked on the focused document
  258.  
  259.             //get the selection
  260.             try
  261.             {
  262.                 var selection = document.commandDispatcher.focusedWindow.getSelection();
  263.                 var reverseSelection = false;
  264.                 if(selection && selection.toString().trim() != "")
  265.                 {
  266.                     //alert(selection.toString());
  267.                     var bubble = this._createBubble();
  268.  
  269.                     //get the index and range and insert our bubble
  270.                     var firstRange = selection.getRangeAt(0);
  271.                     var newRange = doc.createRange();
  272.                     newRange.setStart(selection.focusNode, selection.focusOffset);
  273.                     newRange.setEnd(selection.focusNode, selection.focusOffset);
  274.  
  275.                     if(firstRange.startOffset == selection.focusOffset && firstRange.startContainer == selection.focusNode)
  276.                     {
  277.                         // our new range is before the first range.
  278.                         reverseSelection = true;
  279.  
  280.                         // If it's a reverse selection, popup will make selection changed. Don't know why...
  281.                         // The following code is coping with this issue
  282.                         if(selection.focusNode.nodeType == Node.TEXT_NODE) // is it possible that nodeType is not TEXT?
  283.                         {
  284.                             var tmpRange = doc.createRange();
  285.                             // must backup these values of selection, because it seems that selection properties are changed during the following actions
  286.                             var focusOffset = selection.focusOffset;
  287.                             var anchorOffset = selection.anchorOffset;
  288.  
  289.                             var newTextNode = selection.focusNode.splitText(focusOffset);
  290.                             if(selection.anchorNode == selection.focusNode) // selection is made in the same node
  291.                             {
  292.                                 // keep only the selected text
  293.                                 if(anchorOffset - focusOffset > 0)
  294.                                     newTextNode.splitText(anchorOffset - focusOffset);
  295.  
  296.                                 // remove existing ranges (it should be only one range) because we created a new one
  297.                                 //if(selection.rangeCount == 1)
  298.                                 //    selection.removeAllRanges();
  299.                             }
  300.  
  301.                             //firstRange.setStartAfter(newTextNode); // it seems this method doesn't work properly
  302.  
  303.                             // make sure the original selection still exists
  304.                             tmpRange.selectNodeContents(newTextNode);
  305.  
  306.                             try
  307.                             {
  308.                                 firstRange.setStartAfter(newTextNode);
  309.                             }
  310.                             catch(e)
  311.                             {}
  312.  
  313.                             // add the new range to the selection to make it selected
  314.                             selection.addRange(tmpRange);
  315.  
  316.                             /*if(selection.rangeCount > 1) // some range in current selection already contains content of the tmpRange, so remove the tmpRange
  317.                             {
  318.                                 tmpRange.collapse(true);
  319.                                 selection.removeRange(tmpRange);
  320.                                 tmpRange.detach();
  321.                             }*/
  322.                         }
  323.                     }
  324.                     else
  325.                     {
  326.                         // new range is after the first range. It works well. Nothing to do
  327.                     }
  328.  
  329.                     newRange.insertNode(bubble);
  330.                     newRange.detach();
  331.  
  332.                     // offset the bubble
  333.                     var offset = -(bubble.offsetHeight + 5);
  334.                     bubble.setAttribute("style", "margin-top: " + offset + "px");
  335.  
  336.                     this._attachEventListener(bubble.getElementsByTagName("img"), "click");
  337.  
  338.                     // set the default search info
  339.                     var defaultEngine = BartUniversalSearch.SearchEngineWrapper.getEngine(this.defaultEngineName, true);
  340.                     this._setSearchButtonAttributes(defaultEngine.getName(),
  341.                         defaultEngine.getIconUrl(BartUniversalSearch.UniversalSearchClass.ICON_SEARCHDEFAULT));
  342.                 }
  343.                 else
  344.                 {
  345.                     this.bubble.removeBubble();
  346.                 }
  347.             }
  348.             catch(e)
  349.             {
  350.                 this.bubble.removeBubble();
  351.             }
  352.         },
  353.  
  354.         _setSearchButtonAttributes: function(engineName, iconUrl)
  355.         {
  356.             var searchButton = this._getFocusedDocument().getElementById(BartUniversalSearch.UniversalSearchClass.CMD_ID_SEARCH);
  357.             if(searchButton)
  358.             {
  359.                 searchButton.engine = engineName;
  360.                 // Change icon image and title.
  361.                 searchButton.setAttribute("src", iconUrl);
  362.                 searchButton.setAttribute("title", this._getSearchButtonTitle(engineName));
  363.             }
  364.         },
  365.  
  366.         _getSearchButtonTitle: function(engineName)
  367.         {
  368.             return "Search using " + engineName;
  369.         }
  370.     },
  371.  
  372.     statics:
  373.     {
  374.         _onBubbleEvent: function(event)
  375.         {
  376.             BartUniversalSearch.gSearch._handleBubbleEvent(event);
  377.         },
  378.  
  379.         _loadCssFile: function(fileName)
  380.         {
  381.             var resourceUrl = "chrome://UniversalSearch/skin/" + fileName;
  382.  
  383.             BartUtils.createXMLHttpRequest(
  384.             {
  385.                url: resourceUrl,
  386.                async: false,
  387.                event: "load",
  388.                callback: function(event)
  389.                         {
  390.                             var httpRequest = event.target;
  391.  
  392.                             if(httpRequest.status == 0) // for local file, status is 0 instead of 200
  393.                             {
  394.                                 BartUtils.registerCss(httpRequest.responseText);
  395.  
  396.                                 BartUniversalSearch.UniversalSearchClass.initSuccessful = true;
  397.                             }
  398.                             else
  399.                             {
  400.                                 BartUniversalSearch.UniversalSearchClass.initSuccessful = false;
  401.                             }
  402.                         }
  403.             });
  404.         },
  405.  
  406.         openSearchPage: function(url)
  407.         {
  408.             var type = BartUniversalSearch.Preference.getNewTabType();
  409.             switch(type)
  410.             {
  411.             case 0: // current tab
  412.                 BartBrowserUtils.openNewLocation(url);
  413.                 break;
  414.             case 1: // new tab forground
  415.                 BartBrowserUtils.newTab(url, true);
  416.                 break;
  417.             case 2: // new tab background
  418.                 BartBrowserUtils.newTab(url, false);
  419.                 break;
  420.             }
  421.         },
  422.  
  423.         onPageLoad: function(event)
  424.         {
  425.             var doc = event.originalTarget;
  426.             if(doc.nodeName != "#document" || !doc.location)
  427.             {
  428.                 return;
  429.             }
  430.  
  431.             if(BartUniversalSearch.UniversalSearchClass.initSuccessful)
  432.             {
  433.                 doc.addEventListener("mouseup", BartUniversalSearch.UniversalSearchClass.onMouseup , false);
  434.             }
  435.         },
  436.  
  437.         _loadResources: function()
  438.         {
  439.             //BartUniversalSearch.UniversalSearchClass._loadCssFile("overlay.css");
  440.             BartUtils.loadLocalFile("chrome://UniversalSearch/skin/overlay.css",
  441.                 "text/plain",
  442.                 function(event)
  443.                 {
  444.                     var httpRequest = event.target;
  445.  
  446.                     if(httpRequest.status == 0) // for local file, status is 0 instead of 200
  447.                     {
  448.                         BartUtils.registerCss(httpRequest.responseText);
  449.  
  450.                         BartUniversalSearch.UniversalSearchClass.initSuccessful = true;
  451.                     }
  452.                     else
  453.                     {
  454.                         BartUniversalSearch.UniversalSearchClass.initSuccessful = false;
  455.                     }
  456.                 }
  457.             );
  458.  
  459.             BartUniversalSearch.UniversalSearchClass._loadLocalBinaryResource("copy.png", "ICON_COPY");
  460.             BartUniversalSearch.UniversalSearchClass._loadLocalBinaryResource("search.png", "ICON_SEARCHDEFAULT");
  461.             BartUniversalSearch.UniversalSearchClass._loadLocalBinaryResource("downarrow.png", "ICON_DOWNARROW");
  462.         },
  463.  
  464.         _loadLocalBinaryResource: function(fileName, resultName)
  465.         {
  466.             BartUtils.loadLocalFile("chrome://UniversalSearch/skin/" + fileName,
  467.                 "text/plain; charset=x-user-defined",
  468.                 function(event)
  469.                 {
  470.                     var httpRequest = event.target;
  471.  
  472.                     if(httpRequest.status == 0) // for local file, status is 0 instead of 200
  473.                     {
  474.                         BartUniversalSearch.UniversalSearchClass[resultName] = "data:image/png;base64," + BartUtils.Base64.encode(httpRequest.responseText);
  475.                     }
  476.                 }
  477.             );
  478.         },
  479.  
  480.         init: function()
  481.         {
  482.             BartUniversalSearch.UniversalSearchClass._loadResources();
  483.  
  484.             // init preference and search engines
  485.             BartUniversalSearch.Preference.init();
  486.             BartUniversalSearch.SearchEngineWrapper.init();
  487.  
  488.             BartUniversalSearch.gSearch = new BartUniversalSearch.UniversalSearchClass();
  489.             BartUniversalSearch.gSearch._init();
  490.  
  491.             var appcontent = document.getElementById("appcontent");
  492.             if(appcontent)
  493.             {
  494.                 appcontent.addEventListener("DOMContentLoaded", BartUniversalSearch.UniversalSearchClass.onPageLoad, true);
  495.             }
  496.         },
  497.  
  498.         uninit: function()
  499.         {
  500.             BartUniversalSearch.SearchEngineWrapper.uninit();
  501.         },
  502.  
  503.         onMouseup: function(event)
  504.         {
  505.             setTimeout(function(){BartUniversalSearch.gSearch.onMouseUp(event);}, 100);
  506.             //return BartUniversalSearch.gSearch.onMouseUp(event);
  507.         },
  508.  
  509.         initSuccessful: false, // indicates if our tool is init-ed successfully
  510.  
  511.         CMD_ID_COPY: "BartUniversalSearch_ID_Copy",
  512.         CMD_ID_SEARCH: "BartUniversalSearch_ID_Search",
  513.         CMD_ID_MANAGEENGINE: "BartUniversalSearch_ID_Search_ManageEngines",
  514.         CMD_ID_MORESEARCHES: "BartUniversalSearch_ID_MoreSearches",
  515.         ATTR_CMD_ID: "cmdid",
  516.  
  517.         ICON_COPY: "",
  518.         ICON_SEARCHDEFAULT: "",
  519.         ICON_DOWNARROW: ""
  520.     }
  521. });
  522.  
  523. window.addEventListener("load", BartUniversalSearch.UniversalSearchClass.init, false);
  524. window.addEventListener("unload", BartUniversalSearch.UniversalSearchClass.uninit, false);
  525. //window.addEventListener("mouseup", BartUniversalSearch.UniversalSearchClass.onMouseup , false);
  526.